﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Collections;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Windows.Forms;

namespace Movies
{
    public class HelperDataProvider
    {
        private static HelperDataProvider instanse;
        private List<String> moviesFolders;
        private List<MovieDetails> movieDefinitions;
        private String appPath;
        private HelperDataProvider()
        {
            appPath = Path.GetDirectoryName(Application.ExecutablePath);
            
        }

        public static HelperDataProvider getDataStore()
        {
            if(instanse==null){
                instanse = new HelperDataProvider();
            }
            return instanse;
        }



        public void initDataStore()
        {
            getMoviesFolder();
        }
        
        public List<String> getMoviesFolder()
        {
            if (moviesFolders == null)
            {
                readMovieFolder();
                scanMoviesDetailsChanges();
            }
            return moviesFolders;
        }

        public void scanMoviesDetailsChanges()
        {
            Thread t = new Thread(delegate()
              {
                scanMoviesDetails();
              });
            t.Start();
        }


        public bool isMoviesDefined()
        {
            if (moviesFolders == null || moviesFolders.Count == 0)
            {
                return false;
            }
            return true;
        }

        private void readMovieFolder()
        {
            try
            {
                String folders = HelperSettingProvider.Default().FolderNames;
                if (folders != null && !folders.Trim().Equals(""))
                {
                    moviesFolders = new List<String>();
                    String[] folderNames= folders.Split('|');
                    foreach (String folder in folderNames)
                    {
                        moviesFolders.Add(folder);
                    }
                }
            }
            catch (SystemException ex)
            {
                HelperContentProvider.OmitWarning(ex);
            }
        }

        public void updateMoviesFolder(IEnumerator folders)
        {
            StringBuilder folderText = new StringBuilder();
            moviesFolders = new List<string>();
            while (folders.MoveNext())
            {
                if (folderText.Length > 0)
                {
                    folderText.Append("|");
                }
                folderText.Append(folders.Current.ToString());
                moviesFolders.Add(folders.Current.ToString());
            }
            scanMoviesDetailsChanges();
            HelperSettingProvider.Default().FolderNames = folderText.ToString();
            HelperSettingProvider.Default().Save();
        }

        private List<MovieDetails> scanMoviesDetails()
        {
            return scanMoviesDetails(true);
        }

        [MethodImpl(MethodImplOptions.Synchronized)]
        private List<MovieDetails> scanMoviesDetails(bool forceScan)
        {
            if ((moviesFolders != null && forceScan) || (moviesFolders != null && movieDefinitions == null ))
            {
                skipList = new List<String>();
                movieDefinitions = new List<MovieDetails>();
                if (Directory.Exists(HelperSettingProvider.Default().MovieDataStoreLocation))
                {
                    searchForDetails(HelperSettingProvider.Default().MovieDataStoreLocation, true);
                }

                
                foreach (String dir in moviesFolders)
                {
                    if(Directory.Exists(dir))
                    {
                        searchForDetails(dir);
                    }
                }
            }
            return movieDefinitions;
        }

        private List<String> skipList = new List<string>();

        private void searchForDetails(String dir)
        {
            searchForDetails(dir, false);
        }

        private void searchForDetails(String dir,bool skipOnNoDetails)
        {
            String[] filePaths = Directory.GetDirectories(dir);
            foreach (String fileName in filePaths)
            {
                if (skipList.Contains(fileName))
                {
                    continue;
                }
                String acctualName = null;
                String shortcut = fileName + "\\movie.url";
                if (File.Exists(shortcut))
                {
                    acctualName = readActualLocation(shortcut);
                    if (acctualName != null)
                    {
                        acctualName = acctualName.Replace("/", "\\");
                        skipList.Add(acctualName);
                    }
                }
                else if (skipOnNoDetails)
                {
                    continue;
                }

                //String detailsFileName = fileName + "\\imdb_details.html";                
                MovieDetails details = new MovieDetails(fileName);
                movieDefinitions.Add(details);
                }
            }

        private String readActualLocation(String shortcutFile){
           
            StreamReader stream = new StreamReader(shortcutFile);
            String name = null; 
            String line=null;
            String startStr="URL=file:///";
            while (true)
            {
                line = stream.ReadLine();
                if (line==null)
                {
                    break;
                }
                line= line.Trim();
                if (line.StartsWith(startStr))
                {
                    name = line.Substring(startStr.Length,line.Length-startStr.Length-1);
                    break;
                }
            }
            stream.Close();
            //Console.WriteLine(name);
            return name;
        }

        
        public List<MovieDetails> getMovieDefinitions()
        {
            return scanMoviesDetails(false);
        }


        
        
        private DTOFilter filter;
        
        public void addFilter(DTOFilter filterInput)
        {
            filter = filterInput;
        }

        public bool isFilterDefined()
        {
            if (filter == null)
            {
                return false;
            }
            return true;
        }

        public bool isValidOnFilter(MovieDetails data)
        {
            if (filter == null)
            {
                return true;
            }
            else
            {

                if (filter.SeenStatus != DTOFilter.ALL)
                {
                    bool seenStatus = data.IsAlreadySeen;
                    if (seenStatus && filter.SeenStatus != DTOFilter.ALL_SEEN)
                    {
                        return false;
                    }
                    else if (!seenStatus && filter.SeenStatus != DTOFilter.NOT_SEEN)
                    {
                        return false;
                    }

                }

                if(filter.Title!=null){
                    if (data.Name == null || data.Name.ToLower().IndexOf(filter.Title.ToLower()) == -1)
                    {
                        return false;
                    }
                }

                if (filter.Director != null)
                {
                    if (data.Director == null || data.Director.ToLower().IndexOf(filter.Director.ToLower()) == -1)
                    {
                        return false;
                    }
                }

                if (filter.GetCast() != null)
                {
                    if (data.Actors == null)
                    {
                        return false;
                    }

                    foreach (String cast in filter.GetCast())
                    {
                        if (data.Actors.ToLower().IndexOf(cast.ToLower().Trim()) == -1)
                        {
                            return false;
                        }
                    }
                }

                if (filter.GetWriter() != null)
                {
                    if (data.Writer == null)
                    {
                        return false;
                    }

                    foreach (String writer in filter.GetWriter())
                    {
                        if (data.Writer.ToLower().IndexOf(writer.ToLower().Trim()) == -1)
                        {
                            return false;
                        }
                    }
                }

                if (filter.Genre != null)
                {
                    if (data.GenreList == null)
                    {
                        return false;
                    }

                    foreach (String genre in filter.Genre)
                    {
                        if (data.GenreList.ToLower().IndexOf(genre.ToLower().Trim()) == -1)
                        {
                            return false;
                        }
                    }
                }


                if (filter.RatingHigh != 0)
                {
                    try
                    {
                        Double filterData = Convert.ToDouble(filter.RatingHigh);
                        Double inputData = Convert.ToDouble(data.ImdbRating);
                        if (inputData < filterData)
                        {
                            return false;
                        }
                    }
                    catch (Exception ex)
                    {
                        HelperContentProvider.OmitWarning(ex);
                        return false;
                    }
                }

                if (filter.RatingLow != 10)
                {
                    try
                    {
                        Double filterData = Convert.ToDouble(filter.RatingLow);
                        Double inputData = Convert.ToDouble(data.ImdbRating);
                        if (inputData > filterData)
                        {
                            return false;
                        }
                    }
                    catch (Exception ex)
                    {
                        HelperContentProvider.OmitWarning(ex);
                        return false;
                    }
                }

                if (filter.ReleaseYear != 0)
                {
                    if (data.Year == null)
                    {
                        return false;
                    }
                    try
                    {
                        int inputData = Convert.ToInt32(data.Year);
                        if (inputData > filter.ReleaseYear)
                        {
                            return false;
                        }
                        if (inputData < filter.TillYear)
                        {
                            return false;
                        }
                    }
                    catch (Exception ex)
                    {
                        HelperContentProvider.OmitWarning(ex);
                        return false;
                    }
                }

                if(filter.Rate != null)
                {
                    if(data.Rated == null || !data.Rated.ToLower().Trim().StartsWith(filter.Rate.ToLower()))
                    {
                        return false;
                    }
                }

            }
            return true;

        }

    }
}
